﻿namespace Microsoft.SharePoint.Client
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using System.Text;

    public sealed class JsonReader : IDisposable
    {
        private const string ByteArrayPrefix = "\"\\/Base64Binary(";
        private static int ByteArrayPrefixLength;
        private const string DateTimePrefix = "\"\\/Date(";
        private static int DateTimePrefixLength;
        private const string GuidPrefix = "\"\\/Guid(";
        private static int GuidPrefixLength;
        private long[] m_dateTimeComponents = new long[7];
        private char[] m_dateTimeHhmm = new char[4];
        private char[] m_dateTimeSigns = new char[7];
        private StringBuilder m_decodeStringBuf = new StringBuilder();
        private char[] m_decodeStringHexChars = new char[4];
        private List<Token> m_peekedTokens = new List<Token>();
        private TextPeekReader m_reader;
        private ClientRuntimeContext m_runtimeContext;
        private Stack<Scope> m_scopes = new Stack<Scope>();
        private char[] m_tokenBuffer;
        private byte[] m_tryReadGuidByteBuf = new byte[8];
        private long[] m_tryReadGuidIntBuf = new long[3];
        private static string MaxDoubleValueAsString;
        internal static readonly long MinDateTimeTicks;
        private static string MinDoubleValueAsString;
        private static char[] s_DateTimeComponentSeparator;

        static JsonReader()
        {
            DateTime time = new DateTime(0x7b2, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            MinDateTimeTicks = time.Ticks;
            MinDoubleValueAsString = double.MinValue.ToString(CultureInfo.InvariantCulture);
            MaxDoubleValueAsString = double.MaxValue.ToString(CultureInfo.InvariantCulture);
            s_DateTimeComponentSeparator = new char[] { ',' };
            DateTimePrefixLength = "\"\\/Date(".Length;
            GuidPrefixLength = "\"\\/Guid(".Length;
            ByteArrayPrefixLength = "\"\\/Base64Binary(".Length;
        }

        public JsonReader(TextReader reader, ClientRuntimeContext runtimeContext)
        {
            this.m_reader = new TextPeekReader(reader);
            this.m_tokenBuffer = new char[0x40];
            this.m_runtimeContext = runtimeContext;
            this.SkipWhiteSpace();
        }

        private string DecodeString(int tokenPosition)
        {
            int num;
            if (this.m_reader.Read() != 0x22)
            {
                throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
            }
            StringBuilder decodeStringBuf = this.m_decodeStringBuf;
            decodeStringBuf.Length = 0;
            bool flag = false;
            char[] decodeStringHexChars = this.m_decodeStringHexChars;
            bool flag2 = false;
            while (!flag && ((num = this.m_reader.Read()) != -1))
            {
                char ch;
                if (!flag2)
                {
                    goto Label_0176;
                }
                switch (num)
                {
                    case 0x72:
                        ch = '\r';
                        goto Label_0168;

                    case 0x74:
                        ch = '\t';
                        goto Label_0168;

                    case 0x75:
                    {
                        if (this.m_reader.Read(decodeStringHexChars, 4) != 4)
                        {
                            goto Label_00FC;
                        }
                        int n = 0;
                        if (!this.Hex4ToInt(decodeStringHexChars, out n))
                        {
                            break;
                        }
                        ch = (char) n;
                        goto Label_0168;
                    }
                    case 110:
                        ch = '\n';
                        goto Label_0168;

                    case 0x5c:
                        ch = '\\';
                        goto Label_0168;

                    case 0x22:
                        ch = '"';
                        goto Label_0168;

                    case 0x27:
                        ch = '\'';
                        goto Label_0168;

                    default:
                        throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
                }
                throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
            Label_00FC:;
                throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
            Label_0168:
                decodeStringBuf.Append(ch);
                flag2 = false;
                continue;
            Label_0176:
                switch (num)
                {
                    case 0x5c:
                    {
                        flag2 = true;
                        continue;
                    }
                    case 0x22:
                    {
                        flag = true;
                        continue;
                    }
                }
                decodeStringBuf.Append((char) num);
            }
            if (!flag)
            {
                throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
            }
            return decodeStringBuf.ToString();
        }

        public void Dispose()
        {
            if (this.m_reader != null)
            {
                this.m_reader.Dispose();
            }
        }

        private Token GetTokenPrivate()
        {
            int num = this.m_reader.Peek();
            if (num == -1)
            {
                throw new IndexOutOfRangeException(Resources.GetString("JsonReachTheEndOfStream"));
            }
            Token token = null;
            int offset = this.m_reader.Offset;
            switch (num)
            {
                case 0x2d:
                case 0x30:
                case 0x31:
                case 50:
                case 0x33:
                case 0x34:
                case 0x35:
                case 0x36:
                case 0x37:
                case 0x38:
                case 0x39:
                    token = this.ReadTokenNumber(offset);
                    this.IncreaseObjectCount();
                    return token;

                case 0x22:
                    if ((this.m_scopes.Peek().Type == ScopeType.Object) && ((this.m_scopes.Peek().ObjectCount % 2) == 0))
                    {
                        token = new Token(JsonTokenType.Name, offset) {
                            StringValue = this.DecodeString(offset)
                        };
                        this.SkipWhiteSpaceAndSeparator(':');
                    }
                    else if ((this.m_reader.Peek(1) == 0x5c) && (this.m_reader.Peek(2) == 0x2f))
                    {
                        token = this.TryReadDateTime(offset);
                        if (token != null)
                        {
                            return token;
                        }
                        token = this.TryReadGuid(offset);
                        if (token != null)
                        {
                            return token;
                        }
                        token = this.TryReadByteArray(offset);
                        if (token != null)
                        {
                            return token;
                        }
                    }
                    else
                    {
                        token = new Token(JsonTokenType.String, offset) {
                            StringValue = this.DecodeString(offset)
                        };
                        this.SkipToNextToken();
                    }
                    this.IncreaseObjectCount();
                    return token;

                case 0x5b:
                    token = new Token(JsonTokenType.ArrayStart, offset);
                    this.m_scopes.Push(new Scope(ScopeType.Array));
                    this.m_reader.Skip();
                    this.SkipWhiteSpace();
                    return token;

                case 0x5d:
                    if (this.m_scopes.Peek().Type != ScopeType.Array)
                    {
                        throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { offset }));
                    }
                    token = new Token(JsonTokenType.ArrayEnd, offset);
                    this.m_scopes.Pop();
                    this.m_reader.Skip();
                    this.SkipToNextToken();
                    this.IncreaseObjectCount();
                    return token;

                case 0x7b:
                    token = new Token(JsonTokenType.ObjectStart, offset);
                    this.m_scopes.Push(new Scope(ScopeType.Object));
                    this.m_reader.Skip();
                    this.SkipWhiteSpace();
                    return token;

                case 0x7d:
                    if (this.m_scopes.Peek().Type != ScopeType.Object)
                    {
                        throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { offset }));
                    }
                    token = new Token(JsonTokenType.ObjectEnd, offset);
                    this.m_scopes.Pop();
                    this.m_reader.Skip();
                    this.SkipToNextToken();
                    this.IncreaseObjectCount();
                    return token;

                case 0x74:
                    token = this.ReadTokenTrue(offset);
                    this.IncreaseObjectCount();
                    return token;

                case 0x66:
                    token = this.ReadTokenFalse(offset);
                    this.IncreaseObjectCount();
                    return token;

                case 110:
                    token = this.ReadTokenNull(offset);
                    this.IncreaseObjectCount();
                    return token;
            }
            throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { offset }));
        }

        private bool Hex4ToInt(char[] hexChars, out int n)
        {
            n = 0;
            for (int i = 0; i < hexChars.Length; i++)
            {
                n = n << 4;
                char ch = hexChars[i];
                if ((ch >= '0') && (ch <= '9'))
                {
                    n += ch - '0';
                }
                else if ((ch >= 'a') && (ch <= 'f'))
                {
                    n += (ch - 'a') + 10;
                }
                else if ((ch >= 'A') && (ch <= 'F'))
                {
                    n += (ch - 'A') + 10;
                }
                else
                {
                    return false;
                }
            }
            return true;
        }

        private void IncreaseObjectCount()
        {
            if (this.m_scopes.Count > 0)
            {
                Scope local1 = this.m_scopes.Peek();
                local1.ObjectCount++;
            }
        }

        private bool IsArray(string key, out string fieldName, out Type elementType)
        {
            fieldName = null;
            elementType = null;
            int index = key.IndexOf("$", StringComparison.Ordinal);
            if ((index > 0) && (((index + "$  Array".Length) + 1) < key.Length))
            {
                fieldName = key.Substring(0, index);
                string str = key.Substring(index + 1, ((key.Length - "$  Array".Length) - 1) - index);
                if (DataConvert.StrongTypedArrayElementTypeNames.TryGetValue(str, out elementType))
                {
                    return true;
                }
                elementType = ScriptTypeMap.GetTypeFromScriptType(str);
                if (elementType != null)
                {
                    return true;
                }
            }
            return false;
        }

        private bool IsTokenEnd(int ch)
        {
            if (((!char.IsWhiteSpace((char) ch) && (ch != 0x2c)) && ((ch != 0x3a) && (ch != 0x5d))) && (ch != 0x3b))
            {
                return (ch == 0x7d);
            }
            return true;
        }

        public string PeekName()
        {
            Token token = this.PeekToken();
            if (token.Type != JsonTokenType.Name)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return token.StringValue;
        }

        private Token PeekToken()
        {
            return this.PeekToken(0);
        }

        private Token PeekToken(int tokenPosition)
        {
            while (this.m_peekedTokens.Count < (tokenPosition + 1))
            {
                this.m_peekedTokens.Add(this.GetTokenPrivate());
            }
            return this.m_peekedTokens[tokenPosition];
        }

        private int PeekTokenPosition()
        {
            return this.PeekToken().Position;
        }

        public JsonTokenType PeekTokenType()
        {
            return this.PeekToken().Type;
        }

        public T Read<T>()
        {
            Type type = typeof(T);
            ReadObjectHandler readObjectHandler = ReadObjectHandlers.GetReadObjectHandler(type);
            if (readObjectHandler != null)
            {
                return (T) readObjectHandler(this);
            }
            if (type.IsEnum)
            {
                return this.ReadEnum<T>();
            }
            if (type.IsArray)
            {
                Type elementType = type.GetElementType();
                return (T) typeof(JsonReader).GetMethod("ReadArray").MakeGenericMethod(new Type[] { elementType }).Invoke(this, null);
            }
            return (T) this.ReadObject();
        }

        private static object Read_Boolean(JsonReader reader)
        {
            return reader.ReadBoolean();
        }

        private static object Read_BooleanArray(JsonReader reader)
        {
            return reader.ReadBooleanArray();
        }

        private static object Read_Byte(JsonReader reader)
        {
            return reader.ReadByte();
        }

        private static object Read_ByteArray(JsonReader reader)
        {
            return reader.ReadByteArray();
        }

        private static object Read_Char(JsonReader reader)
        {
            return reader.ReadChar();
        }

        private static object Read_DateTime(JsonReader reader)
        {
            return reader.ReadDateTime();
        }

        private static object Read_DateTimeArray(JsonReader reader)
        {
            return reader.ReadDateTimeArray();
        }

        private static object Read_Double(JsonReader reader)
        {
            return reader.ReadDouble();
        }

        private static object Read_DoubleArray(JsonReader reader)
        {
            return reader.ReadDoubleArray();
        }

        private static object Read_Guid(JsonReader reader)
        {
            return reader.ReadGuid();
        }

        private static object Read_GuidArray(JsonReader reader)
        {
            return reader.ReadGuidArray();
        }

        private static object Read_Int16(JsonReader reader)
        {
            return reader.ReadInt16();
        }

        private static object Read_Int16Array(JsonReader reader)
        {
            return reader.ReadInt16Array();
        }

        private static object Read_Int32(JsonReader reader)
        {
            return reader.ReadInt32();
        }

        private static object Read_Int32Array(JsonReader reader)
        {
            return reader.ReadInt32Array();
        }

        private static object Read_Int64(JsonReader reader)
        {
            return reader.ReadInt64();
        }

        private static object Read_Int64Array(JsonReader reader)
        {
            return reader.ReadInt64Array();
        }

        private static object Read_Single(JsonReader reader)
        {
            return reader.ReadSingle();
        }

        private static object Read_SingleArray(JsonReader reader)
        {
            return reader.ReadSingleArray();
        }

        private static object Read_String(JsonReader reader)
        {
            return reader.ReadString();
        }

        private static object Read_StringArray(JsonReader reader)
        {
            return reader.ReadStringArray();
        }

        private static object Read_UInt16(JsonReader reader)
        {
            return reader.ReadUInt16();
        }

        private static object Read_UInt16Array(JsonReader reader)
        {
            return reader.ReadUInt16Array();
        }

        private static object Read_UInt32(JsonReader reader)
        {
            return reader.ReadUInt32();
        }

        private static object Read_UInt32Array(JsonReader reader)
        {
            return reader.ReadUInt32Array();
        }

        private static object Read_UInt64(JsonReader reader)
        {
            return reader.ReadUInt64();
        }

        private static object Read_UInt64Array(JsonReader reader)
        {
            return reader.ReadUInt64Array();
        }

        public T[] ReadArray<T>()
        {
            if (typeof(T) == typeof(byte))
            {
                return (this.ReadByteArray() as T[]);
            }
            if (this.PeekToken().Type == JsonTokenType.Null)
            {
                this.ReadToken();
                return null;
            }
            List<T> list = new List<T>();
            this.ReadArrayStart();
            while (this.PeekToken().Type != JsonTokenType.ArrayEnd)
            {
                list.Add(this.Read<T>());
            }
            this.ReadArrayEnd();
            return list.ToArray();
        }

        public void ReadArrayEnd()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.ArrayEnd)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
        }

        public void ReadArrayStart()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.ArrayStart)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
        }

        public bool ReadBoolean()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.Boolean)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return token.BoolValue;
        }

        public bool[] ReadBooleanArray()
        {
            Token token = this.ReadToken();
            List<bool> list = new List<bool>();
            if ((token.Type != JsonTokenType.Null) && (token.Type == JsonTokenType.ArrayStart))
            {
                while ((token = this.ReadToken()).Type == JsonTokenType.Boolean)
                {
                    list.Add(token.BoolValue);
                }
                if (token.Type != JsonTokenType.ArrayEnd)
                {
                    throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
                }
            }
            return list.ToArray();
        }

        public byte ReadByte()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.Long)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return (byte) token.LongValue;
        }

        public byte[] ReadByteArray()
        {
            Token token = this.ReadToken();
            if (token.Type == JsonTokenType.Null)
            {
                return null;
            }
            if (token.Type != JsonTokenType.ByteArray)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return token.ByteArrayValue;
        }

        public char ReadChar()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.String)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return token.StringValue[0];
        }

        public DateTime ReadDateTime()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.DateTime)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return token.DateTimeValue;
        }

        public DateTime[] ReadDateTimeArray()
        {
            Token token = this.ReadToken();
            List<DateTime> list = new List<DateTime>();
            if ((token.Type != JsonTokenType.Null) && (token.Type == JsonTokenType.ArrayStart))
            {
                while ((token = this.ReadToken()).Type == JsonTokenType.DateTime)
                {
                    list.Add(token.DateTimeValue);
                }
                if (token.Type != JsonTokenType.ArrayEnd)
                {
                    throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
                }
            }
            return list.ToArray();
        }

        public Dictionary<string, object> ReadDictionary()
        {
            if (this.PeekToken().Type == JsonTokenType.Null)
            {
                this.ReadToken();
                return null;
            }
            this.ReadObjectStart();
            Dictionary<string, object> dictionary = new Dictionary<string, object>();
            while (this.PeekToken().Type != JsonTokenType.ObjectEnd)
            {
                KeyValuePair<string, object> pair = this.ReadKeyValue();
                if ((pair.Key != "_ObjectType_") || !(pair.Value is string))
                {
                    dictionary[pair.Key] = pair.Value;
                }
            }
            this.ReadObjectEnd();
            return dictionary;
        }

        public Dictionary<string, T> ReadDictionary<T>()
        {
            Dictionary<string, object> dictionary = this.ReadDictionary();
            if (dictionary == null)
            {
                return null;
            }
            Dictionary<string, T> dictionary2 = new Dictionary<string, T>();
            foreach (KeyValuePair<string, object> pair in dictionary)
            {
                if (pair.Value is T)
                {
                    dictionary2[pair.Key] = (T) pair.Value;
                }
            }
            return dictionary2;
        }

        public double ReadDouble()
        {
            Token token = this.ReadToken();
            if (token.Type == JsonTokenType.Long)
            {
                return (double) token.LongValue;
            }
            if (token.Type == JsonTokenType.ULong)
            {
                return (double) token.ULongValue;
            }
            if (token.Type != JsonTokenType.Double)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return token.DoubleValue;
        }

        public double[] ReadDoubleArray()
        {
            Token token = this.ReadToken();
            List<double> list = new List<double>();
            if ((token.Type != JsonTokenType.Null) && (token.Type == JsonTokenType.ArrayStart))
            {
                while ((token = this.ReadToken()).Type == JsonTokenType.Double)
                {
                    list.Add(token.DoubleValue);
                }
                if (token.Type != JsonTokenType.ArrayEnd)
                {
                    throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
                }
            }
            return list.ToArray();
        }

        public T ReadEnum<T>()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.Long)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            Type underlyingType = Enum.GetUnderlyingType(typeof(T));
            return (T) Convert.ChangeType(token.LongValue, underlyingType, CultureInfo.InvariantCulture);
        }

        public T[] ReadEnumArray<T>()
        {
            Token token = this.ReadToken();
            List<T> list = new List<T>();
            if ((token.Type != JsonTokenType.Null) && (token.Type == JsonTokenType.ArrayStart))
            {
                while ((token = this.ReadToken()).Type == JsonTokenType.Long)
                {
                    Type underlyingType = Enum.GetUnderlyingType(typeof(T));
                    object obj2 = Convert.ChangeType(token.LongValue, underlyingType, CultureInfo.InvariantCulture);
                    list.Add((T) obj2);
                }
                if (token.Type != JsonTokenType.ArrayEnd)
                {
                    throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
                }
            }
            return list.ToArray();
        }

        public Guid ReadGuid()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.Guid)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return token.GuidValue;
        }

        public Guid[] ReadGuidArray()
        {
            Token token = this.ReadToken();
            List<Guid> list = new List<Guid>();
            if ((token.Type != JsonTokenType.Null) && (token.Type == JsonTokenType.ArrayStart))
            {
                while ((token = this.ReadToken()).Type == JsonTokenType.Guid)
                {
                    list.Add(token.GuidValue);
                }
                if (token.Type != JsonTokenType.ArrayEnd)
                {
                    throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
                }
            }
            return list.ToArray();
        }

        public short ReadInt16()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.Long)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return (short) token.LongValue;
        }

        public short[] ReadInt16Array()
        {
            Token token = this.ReadToken();
            List<short> list = new List<short>();
            if ((token.Type != JsonTokenType.Null) && (token.Type == JsonTokenType.ArrayStart))
            {
                while ((token = this.ReadToken()).Type == JsonTokenType.Long)
                {
                    list.Add((short) token.LongValue);
                }
                if (token.Type != JsonTokenType.ArrayEnd)
                {
                    throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
                }
            }
            return list.ToArray();
        }

        public int ReadInt32()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.Long)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return (int) token.LongValue;
        }

        public int[] ReadInt32Array()
        {
            Token token = this.ReadToken();
            List<int> list = new List<int>();
            if ((token.Type != JsonTokenType.Null) && (token.Type == JsonTokenType.ArrayStart))
            {
                while ((token = this.ReadToken()).Type == JsonTokenType.Long)
                {
                    list.Add((int) token.LongValue);
                }
                if (token.Type != JsonTokenType.ArrayEnd)
                {
                    throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
                }
            }
            return list.ToArray();
        }

        public long ReadInt64()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.Long)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return token.LongValue;
        }

        public long[] ReadInt64Array()
        {
            Token token = this.ReadToken();
            List<long> list = new List<long>();
            if ((token.Type != JsonTokenType.Null) && (token.Type == JsonTokenType.ArrayStart))
            {
                while ((token = this.ReadToken()).Type == JsonTokenType.Long)
                {
                    list.Add(token.LongValue);
                }
                if (token.Type != JsonTokenType.ArrayEnd)
                {
                    throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
                }
            }
            return list.ToArray();
        }

        private object ReadJsonObject()
        {
            Token token = this.PeekToken();
            Token token2 = this.PeekToken(1);
            Token token3 = this.PeekToken(2);
            if (((token.Type == JsonTokenType.ObjectStart) && (token2.Type == JsonTokenType.Name)) && ((token2.StringValue == "_ObjectType_") && (token3.Type == JsonTokenType.String)))
            {
                IFromJson json = ScriptTypeMap.CreateObjectFromScriptType(token3.StringValue, this.Context);
                if (json != null)
                {
                    if (!json.CustomFromJson(this))
                    {
                        json.FromJson(this);
                    }
                    return json;
                }
            }
            this.ReadObjectStart();
            Dictionary<string, object> dictionary = null;
            while ((token = this.PeekToken()).Type != JsonTokenType.ObjectEnd)
            {
                KeyValuePair<string, object> pair = this.ReadKeyValue();
                if (dictionary == null)
                {
                    dictionary = new Dictionary<string, object>();
                }
                dictionary[pair.Key] = pair.Value;
            }
            this.ReadObjectEnd();
            if (dictionary == null)
            {
                dictionary = new Dictionary<string, object>();
            }
            return dictionary;
        }

        public KeyValuePair<string, object> ReadKeyValue()
        {
            if ((this.m_scopes.Count == 0) || (this.m_scopes.Peek().Type != ScopeType.Object))
            {
                throw new InvalidOperationException();
            }
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.Name)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            string stringValue = token.StringValue;
            object obj2 = null;
            bool flag = false;
            if ((stringValue.Length > 8) && (stringValue[stringValue.Length - 8] == '$'))
            {
                switch (stringValue.Substring(stringValue.Length - 8))
                {
                    case "$   Byte":
                        stringValue = stringValue.Substring(0, stringValue.Length - 8);
                        obj2 = this.ReadByte();
                        flag = true;
                        break;

                    case "$   Char":
                        stringValue = stringValue.Substring(0, stringValue.Length - 8);
                        obj2 = this.ReadChar();
                        flag = true;
                        break;

                    case "$  Int16":
                        stringValue = stringValue.Substring(0, stringValue.Length - 8);
                        obj2 = this.ReadInt16();
                        flag = true;
                        break;

                    case "$ UInt16":
                        stringValue = stringValue.Substring(0, stringValue.Length - 8);
                        obj2 = this.ReadUInt16();
                        flag = true;
                        break;

                    case "$  Int32":
                        stringValue = stringValue.Substring(0, stringValue.Length - 8);
                        obj2 = this.ReadInt32();
                        flag = true;
                        break;

                    case "$ UInt32":
                        stringValue = stringValue.Substring(0, stringValue.Length - 8);
                        obj2 = this.ReadUInt32();
                        flag = true;
                        break;

                    case "$  Int64":
                        stringValue = stringValue.Substring(0, stringValue.Length - 8);
                        obj2 = this.ReadInt64();
                        flag = true;
                        break;

                    case "$ UInt64":
                        stringValue = stringValue.Substring(0, stringValue.Length - 8);
                        obj2 = this.ReadUInt64();
                        flag = true;
                        break;

                    case "$ Single":
                        stringValue = stringValue.Substring(0, stringValue.Length - 8);
                        obj2 = this.ReadSingle();
                        flag = true;
                        break;

                    case "$ Double":
                        stringValue = stringValue.Substring(0, stringValue.Length - 8);
                        obj2 = this.ReadDouble();
                        flag = true;
                        break;

                    case "$  Array":
                        string str2;
                        Type type;
                        if (this.IsArray(stringValue, out str2, out type))
                        {
                            stringValue = str2;
                            obj2 = typeof(JsonReader).GetMethod("ReadArray").MakeGenericMethod(new Type[] { type }).Invoke(this, null);
                            flag = true;
                        }
                        break;
                }
            }
            if (!flag)
            {
                obj2 = this.ReadObject();
            }
            return new KeyValuePair<string, object>(stringValue, obj2);
        }

        public List<T> ReadList<T>()
        {
            if (this.PeekToken().Type == JsonTokenType.Null)
            {
                this.ReadToken();
                return null;
            }
            List<T> list = new List<T>();
            this.ReadArrayStart();
            while (this.PeekToken().Type != JsonTokenType.ArrayEnd)
            {
                list.Add(this.Read<T>());
            }
            this.ReadArrayEnd();
            return list;
        }

        public string ReadName()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.Name)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return token.StringValue;
        }

        public object ReadObject()
        {
            Token token = this.PeekToken();
            switch (token.Type)
            {
                case JsonTokenType.ObjectStart:
                    return this.ReadJsonObject();

                case JsonTokenType.ArrayStart:
                    return this.ReadObjectArray();

                case JsonTokenType.String:
                    this.ReadToken();
                    return token.StringValue;

                case JsonTokenType.Long:
                    this.ReadToken();
                    if ((token.LongValue < -2147483648L) || (token.LongValue > 0x7fffffffL))
                    {
                        return token.LongValue;
                    }
                    return (int) token.LongValue;

                case JsonTokenType.ULong:
                    this.ReadToken();
                    return token.ULongValue;

                case JsonTokenType.Double:
                    this.ReadToken();
                    return token.DoubleValue;

                case JsonTokenType.Boolean:
                    this.ReadToken();
                    return token.BoolValue;

                case JsonTokenType.DateTime:
                    this.ReadToken();
                    return token.DateTimeValue;

                case JsonTokenType.Guid:
                    this.ReadToken();
                    return token.GuidValue;

                case JsonTokenType.Null:
                    this.ReadToken();
                    return null;

                case JsonTokenType.ByteArray:
                    return this.ReadByteArray();
            }
            throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
        }

        public object[] ReadObjectArray()
        {
            Token token = this.ReadToken();
            if (token.Type == JsonTokenType.Null)
            {
                return null;
            }
            if (token.Type != JsonTokenType.ArrayStart)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            List<object> list = new List<object>();
            while ((token = this.PeekToken()).Type != JsonTokenType.ArrayEnd)
            {
                object item = this.ReadObject();
                list.Add(item);
            }
            this.ReadArrayEnd();
            return list.ToArray();
        }

        public void ReadObjectEnd()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.ObjectEnd)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
        }

        public void ReadObjectStart()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.ObjectStart)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
        }

        public float ReadSingle()
        {
            Token token = this.ReadToken();
            if (token.Type == JsonTokenType.Long)
            {
                return (float) token.LongValue;
            }
            if (token.Type == JsonTokenType.ULong)
            {
                return (float) token.ULongValue;
            }
            if (token.Type != JsonTokenType.Double)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return (float) token.DoubleValue;
        }

        public float[] ReadSingleArray()
        {
            Token token = this.ReadToken();
            List<float> list = new List<float>();
            if ((token.Type != JsonTokenType.Null) && (token.Type == JsonTokenType.ArrayStart))
            {
                while ((token = this.ReadToken()).Type == JsonTokenType.Double)
                {
                    list.Add((float) token.DoubleValue);
                }
                if (token.Type != JsonTokenType.ArrayEnd)
                {
                    throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
                }
            }
            return list.ToArray();
        }

        public string ReadString()
        {
            Token token = this.ReadToken();
            if (token.Type == JsonTokenType.String)
            {
                return token.StringValue;
            }
            if (token.Type != JsonTokenType.Null)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return null;
        }

        public string[] ReadStringArray()
        {
            Token token = this.ReadToken();
            List<string> list = new List<string>();
            if ((token.Type != JsonTokenType.Null) && (token.Type == JsonTokenType.ArrayStart))
            {
                while (((token = this.ReadToken()).Type == JsonTokenType.String) || (token.Type == JsonTokenType.Null))
                {
                    if (token.Type == JsonTokenType.String)
                    {
                        list.Add(token.StringValue);
                    }
                    else
                    {
                        list.Add(null);
                    }
                }
                if (token.Type != JsonTokenType.ArrayEnd)
                {
                    throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
                }
            }
            return list.ToArray();
        }

        private Token ReadToken()
        {
            Token token = null;
            if (this.m_peekedTokens.Count > 0)
            {
                token = this.m_peekedTokens[0];
                this.m_peekedTokens.RemoveAt(0);
                return token;
            }
            return this.GetTokenPrivate();
        }

        private Token ReadTokenFalse(int tokenPosition)
        {
            int num;
            if (((((num = this.m_reader.Read()) == 0x66) && ((num = this.m_reader.Read()) == 0x61)) && (((num = this.m_reader.Read()) == 0x6c) && ((num = this.m_reader.Read()) == 0x73))) && ((num = this.m_reader.Read()) == 0x65))
            {
                num = this.m_reader.Peek();
                if (this.IsTokenEnd(num))
                {
                    Token token = new Token(JsonTokenType.Boolean, tokenPosition) {
                        BoolValue = false
                    };
                    this.SkipToNextToken();
                    return token;
                }
            }
            throw new FormatException(Resources.GetString("JsonUnknownData", new object[] { tokenPosition }));
        }

        private Token ReadTokenNull(int tokenPosition)
        {
            int num;
            if ((((num = this.m_reader.Read()) == 110) && ((num = this.m_reader.Read()) == 0x75)) && (((num = this.m_reader.Read()) == 0x6c) && ((num = this.m_reader.Read()) == 0x6c)))
            {
                num = this.m_reader.Peek();
                if (this.IsTokenEnd(num))
                {
                    Token token = new Token(JsonTokenType.Null, tokenPosition);
                    this.SkipToNextToken();
                    return token;
                }
            }
            throw new FormatException(Resources.GetString("JsonUnknownData", new object[] { tokenPosition }));
        }

        private Token ReadTokenNumber(int tokenPosition)
        {
            Token token;
            long num3;
            ulong num4;
            int num = this.m_reader.Peek(this.m_tokenBuffer, this.m_tokenBuffer.Length);
            int index = 0;
            while (index < num)
            {
                char ch = this.m_tokenBuffer[index];
                if (this.IsTokenEnd(ch))
                {
                    break;
                }
                index++;
            }
            if ((index == 0) || (index == num))
            {
                throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
            }
            string s = new string(this.m_tokenBuffer, 0, index);
            if (long.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out num3))
            {
                token = new Token(JsonTokenType.Long, tokenPosition) {
                    LongValue = num3
                };
                this.m_reader.Skip(index);
                this.SkipToNextToken();
                return token;
            }
            if (ulong.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out num4))
            {
                token = new Token(JsonTokenType.ULong, tokenPosition) {
                    ULongValue = num4
                };
                this.m_reader.Skip(index);
                this.SkipToNextToken();
                return token;
            }
            double result = 0.0;
            bool flag = false;
            if (s == MinDoubleValueAsString)
            {
                result = double.MinValue;
                flag = true;
            }
            else if (s == MaxDoubleValueAsString)
            {
                result = double.MaxValue;
                flag = true;
            }
            else if (double.TryParse(s, out result))
            {
                flag = true;
            }
            if (!flag)
            {
                throw new FormatException(Resources.GetString("JsonUnknownData", new object[] { tokenPosition }));
            }
            token = new Token(JsonTokenType.Double, tokenPosition) {
                DoubleValue = result
            };
            this.m_reader.Skip(index);
            this.SkipToNextToken();
            return token;
        }

        private Token ReadTokenTrue(int tokenPosition)
        {
            int num;
            if ((((num = this.m_reader.Read()) == 0x74) && ((num = this.m_reader.Read()) == 0x72)) && (((num = this.m_reader.Read()) == 0x75) && ((num = this.m_reader.Read()) == 0x65)))
            {
                num = this.m_reader.Peek();
                if (this.IsTokenEnd(num))
                {
                    Token token = new Token(JsonTokenType.Boolean, tokenPosition) {
                        BoolValue = true
                    };
                    this.SkipToNextToken();
                    return token;
                }
            }
            throw new FormatException(Resources.GetString("JsonUnknownData", new object[] { tokenPosition }));
        }

        public ushort ReadUInt16()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.Long)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return (ushort) token.LongValue;
        }

        public ushort[] ReadUInt16Array()
        {
            Token token = this.ReadToken();
            List<ushort> list = new List<ushort>();
            if ((token.Type != JsonTokenType.Null) && (token.Type == JsonTokenType.ArrayStart))
            {
                while ((token = this.ReadToken()).Type == JsonTokenType.Long)
                {
                    list.Add((ushort) token.LongValue);
                }
                if (token.Type != JsonTokenType.ArrayEnd)
                {
                    throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
                }
            }
            return list.ToArray();
        }

        public uint ReadUInt32()
        {
            Token token = this.ReadToken();
            if (token.Type != JsonTokenType.Long)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return (uint) token.LongValue;
        }

        public uint[] ReadUInt32Array()
        {
            Token token = this.ReadToken();
            List<uint> list = new List<uint>();
            if ((token.Type != JsonTokenType.Null) && (token.Type == JsonTokenType.ArrayStart))
            {
                while ((token = this.ReadToken()).Type == JsonTokenType.Long)
                {
                    list.Add((uint) token.LongValue);
                }
                if (token.Type != JsonTokenType.ArrayEnd)
                {
                    throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
                }
            }
            return list.ToArray();
        }

        public ulong ReadUInt64()
        {
            Token token = this.ReadToken();
            if (token.Type == JsonTokenType.Long)
            {
                return (ulong) token.LongValue;
            }
            if (token.Type != JsonTokenType.ULong)
            {
                throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
            }
            return token.ULongValue;
        }

        public ulong[] ReadUInt64Array()
        {
            Token token = this.ReadToken();
            List<ulong> list = new List<ulong>();
            if ((token.Type != JsonTokenType.Null) && (token.Type == JsonTokenType.ArrayStart))
            {
                while (((token = this.ReadToken()).Type == JsonTokenType.Long) || (token.Type == JsonTokenType.ULong))
                {
                    if (token.Type == JsonTokenType.Long)
                    {
                        list.Add((ulong) token.LongValue);
                    }
                    else
                    {
                        list.Add(token.ULongValue);
                    }
                }
                if (token.Type != JsonTokenType.ArrayEnd)
                {
                    throw new InvalidOperationException(Resources.GetString("JsonDataTypeNotMatch", new object[] { token.Position }));
                }
            }
            return list.ToArray();
        }

        private void SkipToNextToken()
        {
            if ((this.m_scopes.Count > 0) && (this.m_scopes.Peek().Type == ScopeType.Array))
            {
                this.SkipWhiteSpaceAndSeparatorUntilBlockEnd(',', ']');
            }
            else if ((this.m_scopes.Count > 0) && (this.m_scopes.Peek().Type == ScopeType.Object))
            {
                this.SkipWhiteSpaceAndSeparatorUntilBlockEnd(',', '}');
            }
            else
            {
                this.SkipWhiteSpace();
            }
        }

        private void SkipWhiteSpace()
        {
            int num;
            while (((num = this.m_reader.Peek()) != -1) && char.IsWhiteSpace((char) num))
            {
                this.m_reader.Skip();
            }
        }

        private void SkipWhiteSpaceAndSeparator(char separator)
        {
            int num;
            bool flag = false;
            while ((num = this.m_reader.Peek()) != -1)
            {
                if (char.IsWhiteSpace((char) num))
                {
                    this.m_reader.Skip();
                }
                else
                {
                    if (flag || (num != separator))
                    {
                        break;
                    }
                    flag = true;
                    this.m_reader.Skip();
                }
            }
            if (!flag)
            {
                throw new FormatException(Resources.GetString("JsonNotWellFormated"));
            }
        }

        private void SkipWhiteSpaceAndSeparatorUntilBlockEnd(char separator, char blockend)
        {
            int num;
            bool flag = false;
            bool flag2 = false;
            while ((num = this.m_reader.Peek()) != -1)
            {
                if (char.IsWhiteSpace((char) num))
                {
                    this.m_reader.Skip();
                }
                else
                {
                    if (!flag && (num == separator))
                    {
                        flag = true;
                        this.m_reader.Skip();
                        continue;
                    }
                    if (num == blockend)
                    {
                        flag2 = true;
                    }
                    break;
                }
            }
            if (!flag && !flag2)
            {
                throw new FormatException(Resources.GetString("JsonNotWellFormated"));
            }
        }

        private Token TryReadByteArray(int tokenPosition)
        {
            Token token = null;
            int position = 0;
            while ((position < ByteArrayPrefixLength) && (this.m_reader.Peek(position) == "\"\\/Base64Binary("[position]))
            {
                position++;
            }
            if (position == ByteArrayPrefixLength)
            {
                int num;
                token = new Token(JsonTokenType.ByteArray, tokenPosition);
                this.m_reader.Skip(ByteArrayPrefixLength);
                StringBuilder builder = new StringBuilder();
                while (((num = this.m_reader.Read()) != -1) && (num != 0x29))
                {
                    builder.Append((char) num);
                }
                if (((num != 0x29) || (this.m_reader.Read() != 0x5c)) || ((this.m_reader.Read() != 0x2f) || (this.m_reader.Read() != 0x22)))
                {
                    throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
                }
                byte[] buffer = Convert.FromBase64String(builder.ToString().Replace(@"\u002f", "/").Replace(@"\u002F", "/"));
                token.ByteArrayValue = buffer;
                this.SkipToNextToken();
                this.IncreaseObjectCount();
            }
            return token;
        }

        private Token TryReadDateTime(int tokenPosition)
        {
            Token token = null;
            int position = 0;
            while ((position < DateTimePrefixLength) && (this.m_reader.Peek(position) == "\"\\/Date("[position]))
            {
                position++;
            }
            if (position == DateTimePrefixLength)
            {
                int num;
                int num3;
                token = new Token(JsonTokenType.DateTime, tokenPosition);
                this.m_reader.Skip(DateTimePrefixLength);
                char ch = '\0';
                int index = 0;
                bool flag = false;
                bool flag2 = false;
                for (num3 = 0; num3 < this.m_dateTimeComponents.Length; num3++)
                {
                    this.m_dateTimeComponents[num3] = 0L;
                    this.m_dateTimeSigns[num3] = '\0';
                }
                for (index = 0; index < this.m_dateTimeHhmm.Length; index++)
                {
                    this.m_dateTimeHhmm[index] = '\0';
                }
                num3 = 0;
                index = 0;
                bool flag3 = false;
                while (!flag3 && ((num = this.m_reader.Read()) != -1))
                {
                    switch (num)
                    {
                        case 0x20:
                        {
                            flag2 = false;
                            flag = false;
                            continue;
                        }
                        case 0x29:
                        {
                            flag3 = true;
                            continue;
                        }
                        case 0x2b:
                        case 0x2d:
                        {
                            if (!flag2)
                            {
                                goto Label_01D8;
                            }
                            if (num3 != 0)
                            {
                                goto Label_01B4;
                            }
                            ch = (char) num;
                            flag = true;
                            flag2 = false;
                            continue;
                        }
                        case 0x2c:
                        {
                            flag2 = false;
                            flag = false;
                            num3++;
                            if (num3 >= this.m_dateTimeComponents.Length)
                            {
                                throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
                            }
                            continue;
                        }
                        case 0x30:
                        case 0x31:
                        case 50:
                        case 0x33:
                        case 0x34:
                        case 0x35:
                        case 0x36:
                        case 0x37:
                        case 0x38:
                        case 0x39:
                            if (!flag)
                            {
                                goto Label_0171;
                            }
                            if (index >= this.m_dateTimeHhmm.Length)
                            {
                                break;
                            }
                            this.m_dateTimeHhmm[index] = (char) num;
                            index++;
                            goto Label_0178;

                        default:
                            throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
                    }
                    throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
                Label_0171:
                    if (!flag2)
                    {
                        flag2 = true;
                    }
                Label_0178:
                    if (flag2)
                    {
                        this.m_dateTimeComponents[num3] = (this.m_dateTimeComponents[num3] * 10L) + (num - 0x30);
                    }
                    continue;
                Label_01B4:;
                    throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
                Label_01D8:
                    if (this.m_dateTimeSigns[num3] == '\0')
                    {
                        this.m_dateTimeSigns[num3] = (char) num;
                        continue;
                    }
                    throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
                }
                if ((!flag3 || (this.m_reader.Read() != 0x5c)) || ((this.m_reader.Read() != 0x2f) || (this.m_reader.Read() != 0x22)))
                {
                    throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
                }
                for (int i = 0; i < this.m_dateTimeComponents.Length; i++)
                {
                    if (this.m_dateTimeSigns[i] == '-')
                    {
                        this.m_dateTimeComponents[i] = -this.m_dateTimeComponents[i];
                    }
                }
                if (num3 == 0)
                {
                    long num6 = this.m_dateTimeComponents[0];
                    token.DateTimeValue = new DateTime((num6 * 0x2710L) + MinDateTimeTicks, DateTimeKind.Utc);
                    if (ch != '\0')
                    {
                        token.DateTimeValue = token.DateTimeValue.ToLocalTime();
                    }
                }
                else
                {
                    token.DateTimeValue = new DateTime((int) this.m_dateTimeComponents[0], ((int) this.m_dateTimeComponents[1]) + 1, (int) this.m_dateTimeComponents[2], (int) this.m_dateTimeComponents[3], (int) this.m_dateTimeComponents[4], (int) this.m_dateTimeComponents[5], (int) this.m_dateTimeComponents[6], DateTimeKind.Unspecified);
                }
                this.SkipToNextToken();
                this.IncreaseObjectCount();
            }
            return token;
        }

        private Token TryReadGuid(int tokenPosition)
        {
            Token token = null;
            int position = 0;
            while ((position < GuidPrefixLength) && (this.m_reader.Peek(position) == "\"\\/Guid("[position]))
            {
                position++;
            }
            if (position == GuidPrefixLength)
            {
                int num;
                int num3;
                int num4;
                token = new Token(JsonTokenType.Guid, tokenPosition);
                this.m_reader.Skip("\"\\/Guid(".Length);
                for (num3 = 0; num3 < this.m_tryReadGuidByteBuf.Length; num3++)
                {
                    this.m_tryReadGuidByteBuf[num3] = 0;
                }
                for (num4 = 0; num4 < this.m_tryReadGuidIntBuf.Length; num4++)
                {
                    this.m_tryReadGuidIntBuf[num4] = 0L;
                }
                num3 = 0;
                num4 = 0;
                int num5 = 0;
                while (((num = this.m_reader.Read()) != -1) && (num != 0x29))
                {
                    if ((num >= 0x30) && (num <= 0x39))
                    {
                        if (num4 < 3)
                        {
                            this.m_tryReadGuidIntBuf[num4] = ((this.m_tryReadGuidIntBuf[num4] * 0x10L) + num) - 0x30L;
                        }
                        else
                        {
                            this.m_tryReadGuidByteBuf[num3 / 2] = (byte) (((this.m_tryReadGuidByteBuf[num3 / 2] * 0x10) + num) - 0x30);
                            num3++;
                        }
                    }
                    else if ((num >= 0x41) && (num <= 70))
                    {
                        if (num4 < 3)
                        {
                            this.m_tryReadGuidIntBuf[num4] = (((this.m_tryReadGuidIntBuf[num4] * 0x10L) + num) - 0x41L) + 10L;
                        }
                        else
                        {
                            this.m_tryReadGuidByteBuf[num3 / 2] = (byte) ((((this.m_tryReadGuidByteBuf[num3 / 2] * 0x10) + num) - 0x41) + 10);
                            num3++;
                        }
                    }
                    else if ((num >= 0x61) && (num <= 0x66))
                    {
                        if (num4 < 3)
                        {
                            this.m_tryReadGuidIntBuf[num4] = (((this.m_tryReadGuidIntBuf[num4] * 0x10L) + num) - 0x61L) + 10L;
                        }
                        else
                        {
                            this.m_tryReadGuidByteBuf[num3 / 2] = (byte) ((((this.m_tryReadGuidByteBuf[num3 / 2] * 0x10) + num) - 0x61) + 10);
                            num3++;
                        }
                    }
                    else
                    {
                        if (num != 0x2d)
                        {
                            throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
                        }
                        num4++;
                    }
                    num5++;
                }
                if ((((num5 != 0x24) || (num4 != 4)) || ((num3 != 0x10) || (num != 0x29))) || (((this.m_reader.Read() != 0x5c) || (this.m_reader.Read() != 0x2f)) || (this.m_reader.Read() != 0x22)))
                {
                    throw new FormatException(Resources.GetString("JsonNotWellFormated", new object[] { tokenPosition }));
                }
                Guid guid = new Guid((int) this.m_tryReadGuidIntBuf[0], (short) this.m_tryReadGuidIntBuf[1], (short) this.m_tryReadGuidIntBuf[2], this.m_tryReadGuidByteBuf);
                token.GuidValue = guid;
                this.SkipToNextToken();
                this.IncreaseObjectCount();
            }
            return token;
        }

        public ClientRuntimeContext Context
        {
            get
            {
                return this.m_runtimeContext;
            }
        }

        private delegate object ReadObjectHandler(JsonReader reader);

        private static class ReadObjectHandlers
        {
            private static Dictionary<Type, JsonReader.ReadObjectHandler> s_handlers = new Dictionary<Type, JsonReader.ReadObjectHandler>();

            static ReadObjectHandlers()
            {
                s_handlers[typeof(bool)] = new JsonReader.ReadObjectHandler(JsonReader.Read_Boolean);
                s_handlers[typeof(byte)] = new JsonReader.ReadObjectHandler(JsonReader.Read_Byte);
                s_handlers[typeof(char)] = new JsonReader.ReadObjectHandler(JsonReader.Read_Char);
                s_handlers[typeof(short)] = new JsonReader.ReadObjectHandler(JsonReader.Read_Int16);
                s_handlers[typeof(ushort)] = new JsonReader.ReadObjectHandler(JsonReader.Read_UInt16);
                s_handlers[typeof(int)] = new JsonReader.ReadObjectHandler(JsonReader.Read_Int32);
                s_handlers[typeof(uint)] = new JsonReader.ReadObjectHandler(JsonReader.Read_UInt32);
                s_handlers[typeof(long)] = new JsonReader.ReadObjectHandler(JsonReader.Read_Int64);
                s_handlers[typeof(ulong)] = new JsonReader.ReadObjectHandler(JsonReader.Read_UInt64);
                s_handlers[typeof(float)] = new JsonReader.ReadObjectHandler(JsonReader.Read_Single);
                s_handlers[typeof(double)] = new JsonReader.ReadObjectHandler(JsonReader.Read_Double);
                s_handlers[typeof(DateTime)] = new JsonReader.ReadObjectHandler(JsonReader.Read_DateTime);
                s_handlers[typeof(Guid)] = new JsonReader.ReadObjectHandler(JsonReader.Read_Guid);
                s_handlers[typeof(string)] = new JsonReader.ReadObjectHandler(JsonReader.Read_String);
                s_handlers[typeof(bool[])] = new JsonReader.ReadObjectHandler(JsonReader.Read_BooleanArray);
                s_handlers[typeof(byte[])] = new JsonReader.ReadObjectHandler(JsonReader.Read_ByteArray);
                s_handlers[typeof(short[])] = new JsonReader.ReadObjectHandler(JsonReader.Read_Int16Array);
                s_handlers[typeof(ushort[])] = new JsonReader.ReadObjectHandler(JsonReader.Read_UInt16Array);
                s_handlers[typeof(int[])] = new JsonReader.ReadObjectHandler(JsonReader.Read_Int32Array);
                s_handlers[typeof(uint[])] = new JsonReader.ReadObjectHandler(JsonReader.Read_UInt32Array);
                s_handlers[typeof(long[])] = new JsonReader.ReadObjectHandler(JsonReader.Read_Int64Array);
                s_handlers[typeof(ulong[])] = new JsonReader.ReadObjectHandler(JsonReader.Read_UInt64Array);
                s_handlers[typeof(float[])] = new JsonReader.ReadObjectHandler(JsonReader.Read_SingleArray);
                s_handlers[typeof(double[])] = new JsonReader.ReadObjectHandler(JsonReader.Read_DoubleArray);
                s_handlers[typeof(DateTime[])] = new JsonReader.ReadObjectHandler(JsonReader.Read_DateTimeArray);
                s_handlers[typeof(Guid[])] = new JsonReader.ReadObjectHandler(JsonReader.Read_GuidArray);
                s_handlers[typeof(string[])] = new JsonReader.ReadObjectHandler(JsonReader.Read_StringArray);
            }

            public static JsonReader.ReadObjectHandler GetReadObjectHandler(Type type)
            {
                JsonReader.ReadObjectHandler handler = null;
                if (s_handlers.TryGetValue(type, out handler))
                {
                    return handler;
                }
                return null;
            }
        }

        private sealed class Scope
        {
            private int _objectCount;
            private JsonReader.ScopeType _type;

            public Scope(JsonReader.ScopeType type)
            {
                this._type = type;
            }

            public int ObjectCount
            {
                get
                {
                    return this._objectCount;
                }
                set
                {
                    this._objectCount = value;
                }
            }

            public JsonReader.ScopeType Type
            {
                get
                {
                    return this._type;
                }
            }
        }

        private enum ScopeType
        {
            Array,
            Object
        }

        private class Token
        {
            private bool m_boolValue;
            private byte[] m_byteArrayValue;
            private DateTime m_dateTimeValue;
            private double m_doubleValue;
            private Guid m_guidValue;
            private long m_longValue;
            private int m_position;
            private string m_stringValue;
            private JsonTokenType m_tokenType;
            private ulong m_ulongValue;

            public Token(JsonTokenType tokenType, int position)
            {
                this.m_tokenType = tokenType;
                this.m_position = position;
            }

            public bool BoolValue
            {
                get
                {
                    if (this.m_tokenType != JsonTokenType.Boolean)
                    {
                        throw new InvalidOperationException();
                    }
                    return this.m_boolValue;
                }
                set
                {
                    if (this.m_tokenType != JsonTokenType.Boolean)
                    {
                        throw new InvalidOperationException();
                    }
                    this.m_boolValue = value;
                }
            }

            public byte[] ByteArrayValue
            {
                get
                {
                    if (this.m_tokenType != JsonTokenType.ByteArray)
                    {
                        throw new InvalidOperationException();
                    }
                    return this.m_byteArrayValue;
                }
                set
                {
                    if (this.m_tokenType != JsonTokenType.ByteArray)
                    {
                        throw new InvalidOperationException();
                    }
                    this.m_byteArrayValue = value;
                }
            }

            public DateTime DateTimeValue
            {
                get
                {
                    if (this.m_tokenType != JsonTokenType.DateTime)
                    {
                        throw new InvalidOperationException();
                    }
                    return this.m_dateTimeValue;
                }
                set
                {
                    if (this.m_tokenType != JsonTokenType.DateTime)
                    {
                        throw new InvalidOperationException();
                    }
                    this.m_dateTimeValue = value;
                }
            }

            public double DoubleValue
            {
                get
                {
                    if (this.m_tokenType != JsonTokenType.Double)
                    {
                        throw new InvalidOperationException();
                    }
                    return this.m_doubleValue;
                }
                set
                {
                    if (this.m_tokenType != JsonTokenType.Double)
                    {
                        throw new InvalidOperationException();
                    }
                    this.m_doubleValue = value;
                }
            }

            public Guid GuidValue
            {
                get
                {
                    if (this.m_tokenType != JsonTokenType.Guid)
                    {
                        throw new InvalidOperationException();
                    }
                    return this.m_guidValue;
                }
                set
                {
                    if (this.m_tokenType != JsonTokenType.Guid)
                    {
                        throw new InvalidOperationException();
                    }
                    this.m_guidValue = value;
                }
            }

            public bool IsNumber
            {
                get
                {
                    if ((this.m_tokenType != JsonTokenType.Long) && (this.m_tokenType != JsonTokenType.ULong))
                    {
                        return (this.m_tokenType == JsonTokenType.Double);
                    }
                    return true;
                }
            }

            public long LongValue
            {
                get
                {
                    if (this.m_tokenType != JsonTokenType.Long)
                    {
                        throw new InvalidOperationException();
                    }
                    return this.m_longValue;
                }
                set
                {
                    if (this.m_tokenType != JsonTokenType.Long)
                    {
                        throw new InvalidOperationException();
                    }
                    this.m_longValue = value;
                }
            }

            public int Position
            {
                get
                {
                    return this.m_position;
                }
            }

            public string StringValue
            {
                get
                {
                    if (((this.m_tokenType != JsonTokenType.Name) && (this.m_tokenType != JsonTokenType.String)) || (this.m_stringValue == null))
                    {
                        throw new InvalidOperationException();
                    }
                    return this.m_stringValue;
                }
                set
                {
                    if (((this.m_tokenType == JsonTokenType.Name) || (this.m_tokenType == JsonTokenType.String)) && (value != null))
                    {
                        this.m_stringValue = value;
                    }
                }
            }

            public JsonTokenType Type
            {
                get
                {
                    return this.m_tokenType;
                }
            }

            public ulong ULongValue
            {
                get
                {
                    if (this.m_tokenType != JsonTokenType.ULong)
                    {
                        throw new InvalidOperationException();
                    }
                    return this.m_ulongValue;
                }
                set
                {
                    if (this.m_tokenType != JsonTokenType.ULong)
                    {
                        throw new InvalidOperationException();
                    }
                    this.m_ulongValue = value;
                }
            }
        }
    }
}

